home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SPACE 2
/
SPACE - Library 2 - Volume 1.iso
/
program
/
331
/
gemfst14
/
gemxtend.doc
< prev
next >
Wrap
Text File
|
1990-07-20
|
22KB
|
460 lines
**************************************************************************
*
* GEMXTEND.DOC - Descriptions of extensions made to GEM bindings since
* the original TOS 1.0 release.
*
* 05/26/90 - v.4
* Included documentation on the new calling standard,
* and the bindings that currently support it:
* evnx_multi()
* frmx_center()
* winx_get()
* winx_calc()
*
* 09/06/89 - v1.3
* This document is new with this release, and contains
* revisions through TOS 1.4.
**************************************************************************
This document is divided into two sections. Section 1 documents the
changes and additions Atari has made to the GEM routines in TOS. Section 2
documents alternate calling standards to the existing functions. These
alternate bindings provide more efficient ways to call AES functions.
**************************************************************************
*
* Section 1 - Changes Atari has made to GEM/TOS.
*
**************************************************************************
This section describes extensions Atari has made to TOS/GEM since the
original TOS 1.0 operating system. When Atari adds new VDI/AES functions,
appropriate bindings will be created and documented here. Note that some
of the functions listed here have been available since TOS 1.0, but Atari
neglected to document them. The title bar for each function lists the
first TOS version that supported the function. Other functions have
backwards compatibility built into the GEMFAST binding so that they will
work correctly on all TOS versions (these are noted in the title bars too).
*--------------------------------------------------------------------------
* About TOS 1.4...
*--------------------------------------------------------------------------
The TOS 1.4 pre-release notes contain documentation for the following:
form_error form_alert shel_write shel_get shel_put
fsel_exinput wind_new
Of these, the form_error/alert and shel_???? docs seem to be just a
clarification of the docs without any functional changes.
The wind_new and fsel_exinput functions are new with TOS 1.4.
;-------------------------------------------------------------------------
; wind_new TOS 1.4
;-------------------------------------------------------------------------
void wind_new();
The 'wind_new' function is for doing a major cleanup after a GEM
application. It closes & deletes all windows, flushes all the windows'
buffers (of redraw msgs, I presume), clears the wind_update flag, and
restores ownership of the mouse to the system (END_MCTRL I presume). The
documentation is not clear on whether this function should be used by
an application that wants to shut down everything quickly, or whether it
is intended for a shell's use in cleaning up after an application exits.
I tend to suspect the latter, and I think this function was developed
because shell writers all begged Atari to provide something that could
clean up after an application the way the desktop does.
;-------------------------------------------------------------------------
; fsel_exinput TOS 1.4 (binding compatible with 1.0 and up)
;-------------------------------------------------------------------------
Full 1.4 emulation...
status = fsel_exinput(in_path, in_sel, &exitbtn, prompt_text);
(status and exitbtn are 16-bit ints, others are char *).
This routine is functionally equivelent to fsel_input, except that it
also allows you to specify a prompt string of up to 30 characters to be
displayed along with the file selector. While the function is new with
TOS 1.4, the AESFAST bindings support it in all versions via a routine
which checks the AES version number and simulates the actions of
fsel_exinput by using fsel_input and objc_draw. If running under
TOS 1.4, the system will display your prompt text in place of the words
'FILE SELECTOR' inside the fsel box. If running under pre-TOS 1.4, the
simulation routines place the prompt text in a box which appears
between the menu bar and the fsel box.
Other TOS 1.4 changes to the fsel routines that this routine supports
via simulation when running on pre-TOS 1.4 systems...
- The file selector now allows you to edit the pathname and hit RETURN
without exiting the dialog. If you edit the filename and hit <CR>,
you will exit as if you clicked on OK.
- If the initial pathname has a leading '\', it will be appended to the
end of the current default drive and path, and the entire resulting
string will be returned if the user exits via OK or <CR>.
- The current default drive and path are preserved, and the contents
of the current DTA are preserved. Only the default path on the
default drive is saved with the simulation software. If the user
changes devices during file selection, the default path on all devices
may be changed except for the device that was the default when
fsel_exinput was called.
The executable code for the fsel_exinput binding is big -- about 800
bytes. Also, it uses about 350 bytes of stack space during the call.
Still, having a prompted file selector that works correctly on all
machines will lend a touch of class to your application (IMHO).
Note that all of the above fsel ehancements which are supported by the
simulation on pre-TOS 1.4 systems are supported ONLY if you call
fsel_exinput; if you call fsel_input on a pre-1.4 system the default
path et. al. will behave as they always have. (Hint: USE exinput).
;-------------------------------------------------------------------------
; fsel_smallexinput TOS 1.4 (binding compatible with 1.0 and up)
;-------------------------------------------------------------------------
Prompting emulation only...
This function has calling parameters identical to fsel_exinput() (see
above), but it's behavior (return values, etc) is identical to that of
fsel_input() (the original). This function will call the real 'exinput'
routine if on TOS 1.4, but if on an earlier version it emulates only the
prompting of 'exinput', it does not save the path or DTA, or handle <CR>
correctly, or any of the other nice TOS 1.4 features. On the other hand,
it's only half as big as the full emulator for fsel_exinput(), so it's
handy for accessories and other small-memory applications. (It will add
about 450 bytes to your program, as opposed to 800).
I'd like to recommend that you do not code calls to fsel_smallexinput()
directly in your program. Instead, just code fsel_exinput(), and at the
top of your C source, code:
#define fsel_exinput fsel_smallexinput
and let the C compiler handle the rest for you. This ought to keep your
code compatible many years into the future...
;-------------------------------------------------------------------------
; fsel_14input TOS 1.4 (binding compatible with 1.0 and up)
;-------------------------------------------------------------------------
No emulation.
This function has calling parameters identical to fsel_exinput() (see
above). However, it makes no attempt to emulate any of the 1.4 exinput
features. Basically, if running on TOS 1.4, fsel_exinput is called. If
running on a pre-1.4 system, the prompt string is thrown away, and the
normal file selector is called. This binding is very small compared to
other (emulation mode) exinput bindings.
Again, it is best to access this function through a #define statement:
#define fsel_exinput fsel_14input
| This function was added with v1.4.
;-------------------------------------------------------------------------
; shel_get / shel_put TOS 1.0
;-------------------------------------------------------------------------
status = shel_get(char *bufadr, int buflen)
status = shel_put(char *bufadr, int buflen)
These functions read and write the desktop's internal buffer
which holds a copy of the DESKTOP.INF file. The buffer holds
an exact image of the file, in plain ASCII text. If 'status'
is returned as zero, an error occurred. The Atari docs say that
the buffer should never exceed 1024 bytes, but I've been told
that it *can* in fact exceed this length.
;-------------------------------------------------------------------------
; form_keybd TOS 1.0
;-------------------------------------------------------------------------
keyret = form_keybd(tree, object, nxtobject, thechar, &nxtobject, &thechar);
(All values are 16-bit words, except 'tree', which is OBJECT *).
The form_keybd routine acts as a filter on character input.
When it recognizes a control character, it processes
it and zeroes the keyboard word. Other chararacters can be
passed on to objc_edit to be inserted in the editable object.
If the routine returns a zero, a default object is selected (<CR>).
(Hints: If 'nxtobject' is not equal to 'object' after this call,
form_keybd() has detected a TAB or ARROW key to move to the next
edit field, so call objc_edit(..., EDEND) for the current field,
as long as nxtobject is non-zero. If 'thechar' comes back non-zero,
pass it to objc_edit(..., EDCHAR). If this doesn't make sense, get
the Tim Oren articles and make your own interpretations.)
;-------------------------------------------------------------------------
; form_button TOS 1.0
;-------------------------------------------------------------------------
btnret = form_button(tree, object, clicks, &nxtobject);
(All values are 16-bit words, except 'tree', which is OBJECT *).
I can't tell you as much about this one. This routine handles an
already-occurred mouse button event. It handles changing the
selected object into reverse video. It (presumably) handles radio
buttons. 'object' is the index of the object the mouse is over, so
I presume have have to call objc_find() first to get this. 'nxtobject'
is the new selected object index. If the routine returns a zero,
a default or exit object was selected.
**************************************************************************
*
* Section 2 - An alternate calling standard, and supporting bindings...
*
**************************************************************************
BACKGROUND
The calling standard for AES functions defined and documented by DRI was
defined for ease of use in C programming, but it does not lend itself to
particularly efficient code generation. For example, the wind_get() call
can be used to return many different types of values, so DRI defined the
function as taking pointers to 4 separate output fields. However, one of
most common functions for wind_get() is to return information about window
rectangles; the values are returned in typical GRECT order.
In the old days, a call of this type was often coded as:
wind_get(wi_handle, WF_CURRXYWH, &x, &y, &w, &h);
As GEM coding techniques have become more sophisticated, people have found
that it makes more sense to keep xywh values in GRECT structures instead of
in discrete variables. This leads to the rather cumbersome construct:
wind_get(wi_handle, WF_CURRXYWH,
&windrect.g_x, &windrect.g_y,
&windrect.g_w, &windrect.g_h);
When ideally, one would prefer to code:
wind_get(wi_handle, WF_CURRXYWH, &windrect);
This makes a huge difference in runtime performance. When the binding for
the original wind_get() routine is called, it has no idea whether discrete
(possibly discontiguous) addresses are passed, so it must build a temporary
output array on the stack in which the AES can pass return values. Upon
return from the AES, the binding must copy each of the four return values
back to the caller's memory, using the 4 individual pointers specified.
Using the alternate calling standard, the binding can simply pass the AES
the GRECT pointer specified in the call, and the AES can place the returned
values directly into the caller's memory, avoiding intermediate arrays.
Also, the C compiler only has to stack one address when setting up the call.
STANDARDS
Because it is not possible to have one function name to handle both types
of calling standards, I have choosen to implement the alternate bindings
using similar names, with an 'x' to indicate it is one of the extended
bindings. Thus, wind_get() would be called when discrete addresses are
passed, and winx_get() would be called when a single pointer is passed.
There will be a certain amount of schizophrenia in the alternate binding
standards. Some functions (such as evnx_multi) will take all input and
output values in a single consolidated structure. Others will pass
discrete input values, but take the return values in a structure, or
vice versa. I will try to use common sense when making such decisions;
what I want to avoid is the VDI mess. With VDI calls, you have to load
*everything* into an array, even when it doesn't seem to make sense to
do so. I think VDI coding is very tedious for this reason, and I'm going
to try to avoid that with the alternate AES bindings.
As an aside: I've heard rumours that Tim Oren defined an entire alternate
calling structure for the AES under the name GEMX. Unfortunately, I can't
find out anything about it except that it 'may exist'. Therefore, nothing
in my alternate calling standards are going to correspond to his, except
by accident. If anybody has more info on GEMX, I'd love to learn about it.
IMPLEMENTATION
I had planned to write the entire set of alternate bindings and release
them as GemFast v2.0. I've been planning that for months, and it isn't
working out. Therefore, beginning with v1.4, I'm releasing things as I
go. As of 1.4, there are only a couple of these extended bindings
available.
X-STRUCTURES
Where custom data structures are needed by an alternate binding, the
structures will be documented with the binding(s) that use them. All such
structures are defined in the GEMFAST.H header file.
;-------------------------------------------------------------------------
; evnx_multi - Alternate for evnt_multi.
;-------------------------------------------------------------------------
int evnx_multi(XMULTI *xm);
This binding takes a single parm, a pointer to an XMULTI structure. It
returns an integer, which is a bit mask of events which occurred (the
same value returned by evnt_multi). This mask is also returned in
the mwhich element of the XMULTI structure.
All of the values normally passed to evnt_multi are included in the
XMULTI structure. All of the output values are returned in the XMULTI
structure, including messages in the message buffer, which is the 1st
eight words of the XMULTI structure.
The XMULTI structure is defined as follows:
typedef struct xmulti {
int msgbuf[8]; /* Message buffer */
int mflags; /* Mask of events to wait for */
int mbclicks, /* Button clicks to wait for */
mbmask, /* Which buttons to wait for */
mbstate; /* Button state to wait for */
int mm1flags; /* M1 rect: wait for in/out flag*/
GRECT mm1rect; /* M1 rect: xywh coordinates */
int mm2flags; /* M2 rect: wait for in/out flag*/
GRECT mm2rect; /* M2 rect: xywh coordinates */
int mtlocount, /* Timer count low value */
mthicount; /* Timer count high value */
int mwhich, /* Mask of events that occurred */
mmox, /* Mouse x at time of event */
mmoy, /* Mouse y at time of event */
mmobutton, /* Mouse buttons at event */
mmokstate, /* Keystate at event */
mkreturn, /* Key pressed at event */
mbreturn; /* Times buttons was clicked */
} XMULTI;
It is most efficient to code the XMULTI structure as a local variable
of the function that uses it, although it can be defined as a global
or static variable. A simple, typical multi-handler might look like:
multi()
{
XMULTI xm;
int events
/*
* set up static portions of xm structure...
*/
xm.mflags = MU_TIMER | MU_MESAG | MU_BUTTON;
xm.tlocount = 1000; /* 1 second */
xm.thicount = 0; /* timer value */
xm.mbclicks = 1; /* wait for single */
xm.mbmask = 1; /* click of left */
xm.mbstate = 1; /* button */
while (1) {
events = evnx_multi(&xm);
if (events & MU_BUTTON) {
handle_button(xm.mox, xm.moy);
}
if (events & MU_TIMER) {
handle_timeout();
}
if (events & MU_MESAG) {
switch(xm.msgbuf[0]) {
case WM_REDRAW:
do_redraw(xm.msgbuf[3], &xm.msgbuf[4]);
break;
case MN_SELECTED:
do_menuitem(xm.msgbuf[3], xm.msgbuf[4]);
break;
/* etc */
} /* end switch */
} /* end if (MU_MESAG) */
} /* end while(1) */
} /* end multi() function */
As can be seen in the example, this can be much more efficient than
the usual call to evnt_multi, because it is not necessary to stack
50-some bytes of info on each loop iteration. Also, the binding for
envx_multi is *much* smaller and faster than the one for evnt_multi.
;-------------------------------------------------------------------------
; winx_get - Alternate for wind_get
;-------------------------------------------------------------------------
int winx_get(int whandle, int wfield, GRECT *outrect);
This binding takes the same 2 input parms as wind_get; the window
handle, and a value indicating the window info to be returned. For
output, it takes a pointer to a GRECT structure. The return value is
the same as for wind_get() (0 indicates error).
Note that the pointer to the output doesn't *have* to be a GRECT
pointer, it is more specifically a pointer to 4 contiguous words of
storage which will hold the return values. The only wind_get()
functions which return more than a single value all return GRECT type
output, however.
If winx_get() is called with a wfield value that implies just one
return value (WF_TOP, for example), you must be aware that EIGHT BYTES
OF MEMORY WILL BE MODIFIED at the location pointed to by the output
pointer. (All but the first 2 bytes will be garbage, of course).
Usage example:
GRECT currect;
winx_get(wi_handle, WF_CURRXYWH, &currect);
;-------------------------------------------------------------------------
; frmx_center - Alternate for form_center
;-------------------------------------------------------------------------
int frmx_center(OBJECT *ptree, GRECT *outrect);
This binding takes a pointer to an object tree (as form_center does),
and a pointer to a GRECT where the output xywh values will be returned.
The return value from the function is always 1, as for form_center.
Example:
GRECT treerect;
frmx_center(ptree, &treerect);
objc_draw(ptree, R_TREE, MAX_DEPTH, treerect);
;-------------------------------------------------------------------------
; winx_calc - Alternate for wind_calc
;-------------------------------------------------------------------------
int winx_calc(int type, kind, in_x, in_y, in_w, in_h, GRECT *outrect);
This binding takes all the same input values as wind_calc, but returns
the output in a GRECT structure. Note that although the input xywh
values are listed as discrete in the definition above, your compiler
will accept the name of a GRECT as the third parameter, and will
stack the four values from the rectangle as discrete parms.
The following example might be used to create a window around an
object tree...
int wi_kind = MOVER | FULLER | CLOSER;
GRECT workrect;
GRECT fullrect;
frmx_center(tree, &workrect);
winx_calc(WC_BORDER, wi_kind, workrect, &fullrect);
wi_handle = wind_create(wi_kind, fullrect);
if (wi_handle >= 0)
wind_open(wi_handle, fullrect);
**************************************************************************
* END OF GEMXTEND DOC
**************************************************************************